﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;

namespace BattleforgeAssault
{
    public class Controller : GameObject
    {
        private Game _game;
        public Game Game { get { return _game; } }

        private GameView _view;
        public GameView View { get { return _view; } }

        private Query _currentQuery = null;
        public Query CurrentQuery { get { return _currentQuery; } set { _currentQuery = value; RaisePropertyChanged("CurrentQuery"); } }

        private int _minTargets = 0;
        private int _maxTargets = int.MaxValue;

        private List<GameObject> _currentTargets = new List<GameObject>();
        public List<GameObject> CurrentTargets { get { return _currentTargets; } set { _currentTargets = value; RaisePropertyChanged("Targets"); } }

        public Controller(GameView view)
        {
            _view = view;

            _game = new Game(this);
        }

        public void Start()
        {
            _game.Setup();

            ThreadPool.QueueUserWorkItem((g) =>
            {
                Game game = g as Game;
                game.Begin();
            }, _game);
        }

        private void DispatchCall(System.Action method)
        {
            if (Deployment.Current.Dispatcher.CheckAccess()) { method(); }
            else { Deployment.Current.Dispatcher.BeginInvoke(method); }
        }

        public void QueryPlayer(Query query)
        {
            DispatchCall(() =>
            {
                CurrentQuery = query;
                _view.queryArea.DataContext = CurrentQuery;
                _view.queryArea.Visibility = Visibility.Visible;
                _view.queryDoneButton.Focus();
            });
        }

        public void AnswerQuery()
        {
            DispatchCall(() =>
            {
                CurrentQuery.Answer = _view.queryAnswerList.SelectedIndex;
                _game.IsWaiting = false;
                _view.queryArea.Visibility = Visibility.Collapsed;
            });
        }

        public void SelectTargets(string message, int min, int max, Func<GameObject, bool> targetIsValid)
        {
            DispatchCall(() =>
            {
                CurrentTargets.Clear();
                _minTargets = min;
                _maxTargets = max;

                // check each card
                foreach (FrameworkElement element in _view.CardLayer.Children)
                {
                    if (element.DataContext is Card)
                    {
                        var view = element as CardView;
                        var card = view.Card;
                        if (!targetIsValid(card))
                        {
                            view.Dim(true);
                        }
                    }
                }

                foreach (FrameworkElement element in _view.LocationLayer.Children)
                {
                    if (element.DataContext is Location)
                    {
                        var view = element as LocationView;
                        var location = view.Location;
                        if (!targetIsValid(location))
                        {
                            view.Dim(true);
                        }
                    }
                }

                // TODO: allow selecting players

                _view.targetsDescription.Text = message;
                _view.targetsArea.Visibility = Visibility.Visible;
                _view.targetDoneButton.Focus();
            });
        }

        public void ReturnTargets()
        {
            DispatchCall(() =>
            {
                if (_minTargets > 0 && !(CurrentTargets.Count >= _minTargets))
                {
                    // not enough targets
                    MessageBox.Show("Choose more targets");
                    return;
                }

                if (_maxTargets > 0 && !(CurrentTargets.Count <= _maxTargets))
                {
                    // too many targets
                    MessageBox.Show("Choose fewer targets");
                    return;
                }

                foreach (FrameworkElement element in _view.CardLayer.Children)
                {
                    if (element.DataContext is Card)
                    {
                        var view = element as CardView;
                        var card = view.Card;
                        view.Dim(false);
                        if (CurrentTargets.Contains(card))
                        {
                            view.Select(false);
                        }
                    }
                }

                foreach (FrameworkElement element in _view.LocationLayer.Children)
                {
                    if (element.DataContext is Location)
                    {
                        var view = element as LocationView;
                        var location = view.Location;
                        view.Dim(false);
                        if (CurrentTargets.Contains(location))
                        {
                            view.Select(false);
                        }
                    }
                }

                _game.IsWaiting = false;
                _view.targetsArea.Visibility = Visibility.Collapsed;
            });
        }
    } // Class
} // Namespace
